package com.ruoyi.system.service.impl;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.csp.sentinel.util.AssertUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.core.constant.Constants;
import com.ruoyi.common.core.utils.CommonStreamUtil;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.Helper;
import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.system.domain.BaseTournament;
import com.ruoyi.system.domain.LiveStreamCode;
import com.ruoyi.system.mapper.BaseTournamentMapper;
import com.tencentcloudapi.live.v20180801.models.CreateCommonMixStreamRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.system.mapper.BaseLiveTournamentMapper;
import com.ruoyi.system.domain.BaseLiveTournament;
import com.ruoyi.system.service.IBaseLiveTournamentService;

import javax.annotation.Resource;

/**
 * 比赛直播房间Service业务层处理
 *
 * @author ruoyi
 * @date 2024-05-10
 */
@Service
@Slf4j
public class BaseLiveTournamentServiceImpl extends ServiceImpl<BaseLiveTournamentMapper, BaseLiveTournament> implements IBaseLiveTournamentService {
    @Resource
    private BaseLiveTournamentMapper baseLiveTournamentMapper;

    @Resource
    LoginUserSetUtil loginUserSetUtil;

    @Resource
    LiveService liveService;

    @Resource
    private RedisService redisService;
    @Resource
    private BaseTournamentMapper baseTournamentMapper;


    /**
     * 查询比赛直播房间
     *
     * @param id 比赛直播房间主键
     * @return 比赛直播房间
     */
    @Override
    public BaseLiveTournament selectBaseLiveTournamentById(Long id) {
        return baseLiveTournamentMapper.selectBaseLiveTournamentById(id);
    }

    /**
     * 查询比赛直播房间列表
     *
     * @param baseLiveTournament 比赛直播房间
     * @return 比赛直播房间
     */
    @Override
    public List<BaseLiveTournament> selectBaseLiveTournamentList(BaseLiveTournament baseLiveTournament) {
        baseLiveTournament.setType(Objects.equals(baseLiveTournament.getType(),0)?0:2);
        return baseLiveTournamentMapper.selectBaseLiveTournamentList(baseLiveTournament);
    }

    /**
     * 新增比赛直播房间
     *
     * @param baseLiveTournament 比赛直播房间
     * @return 结果
     */
    @Override
    public int insertBaseLiveTournament(BaseLiveTournament baseLiveTournament) {
        AssertUtil.notNull(baseLiveTournament.getTournamentId(), "赛事id不能为空");
        AssertUtil.notNull(baseLiveTournament.getRoomNumber(), "房间号不能为空");
        AssertUtil.notNull(baseLiveTournament.getLiveEndTime(), "房间结束时间不能为空");
//        AssertUtil.notNull(baseLiveTournament.getPushUrl(), "推流地址不能为空");
        AssertUtil.notNull(baseLiveTournament.getViewUrl(), "播放地址不能为空");

        LambdaQueryWrapper<BaseLiveTournament> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BaseLiveTournament::getTournamentId, baseLiveTournament.getTournamentId());
        List<BaseLiveTournament> liveTournament = baseMapper.selectList(queryWrapper);

        if(CollUtil.isNotEmpty(liveTournament)){
            baseMapper.deleteBatchIds(CommonStreamUtil.transSet(liveTournament,BaseLiveTournament::getId));
        }
        //新增
        loginUserSetUtil.populateFields(baseLiveTournament, 1);
        return baseMapper.insert(baseLiveTournament);
    }

    /**
     * 批量删除比赛直播房间
     *
     * @param ids 需要删除的比赛直播房间主键
     * @return 结果
     */
    @Override
    public int deleteBaseLiveTournamentByIds(Long[] ids) {
        return baseLiveTournamentMapper.deleteBaseLiveTournamentByIds(ids);
    }

    /**
     * 删除比赛直播房间信息
     *
     * @param id 比赛直播房间主键
     * @return 结果
     */
    @Override
    public int deleteBaseLiveTournamentById(Long id) {
        return baseLiveTournamentMapper.deleteBaseLiveTournamentById(id);
    }

    /**
     * 开始直播
     *
     * @param tournamentId
     * @return
     */
    @Override
    public LiveStreamCode beginLive(Long tournamentId, LocalDateTime endTime,Integer type) {
        //获取房间号
        String streamName = tournamentId + Helper.generateRandomCharacter(6);

        //获取不重复的房间号
        while (findByStreamName(streamName)) {
            streamName = tournamentId +  Helper.generateRandomCharacter(6);
        }
        log.info("直播参数-》streamName:{},endTime:{},type:{}",streamName,endTime,type);

        //获取推流信息
        LiveStreamCode obsCode = liveService.getOBSCode(streamName, endTime, type,tournamentId);


        BaseTournament baseTournament = baseTournamentMapper.selectById(tournamentId);
        Integer equipmentSwitch = baseTournament.getEquipmentSwitch();

        BaseLiveTournament baseLiveTournament = new BaseLiveTournament();
        baseLiveTournament.setTournamentId(tournamentId)
                .setLiveEndTime(endTime)
                .setState(0)
                .setRoomNumber(obsCode.getStreamName())
                .setPushUrl(obsCode.getObsServer())
                .setType(Objects.equals(equipmentSwitch,0)?0:2)
                .setViewUrl(obsCode.getPlayCode());
//        this.insertBaseLiveTournament(baseLiveTournament);
        log.info("直播参数缓存:{}",JSON.toJSONString(baseLiveTournament));
        redisService.setCacheObject(streamName, JSON.toJSONString(baseLiveTournament),30L, TimeUnit.MINUTES);

        return obsCode;
    }

    /**
     * 关闭直播
     *
     * @param streamName
     * @return
     */
    @Override
    public int endLive(String streamName) {
        //关闭直播
        liveService.dropLiveStream(streamName);

//        //未报异常执行更改状态
//        BaseLiveTournament liveTournament = getBaseLiveTournament(streamName);
//        //更改为已结束
//        liveTournament.setState(2);
//        loginUserSetUtil.populateFields(liveTournament,2);

        return 1;

    }

    @Override
    public void liveNum(Long tournamentId) {
        Object cacheObject = redisService.getCacheObject(Constants.LIVE_NUM + tournamentId);
        long num = cacheObject == null ? 0 : Long.valueOf((Integer) cacheObject);
        long l = num + 100;
        redisService.setCacheObject(Constants.LIVE_NUM + tournamentId,l);

        baseTournamentMapper.updateBaseTournament(new BaseTournament().setId(tournamentId).setLiveNum(l));
    }

    @Override
    public BaseLiveTournament selectByTournamentId(Long tournamentId) {
        LambdaQueryWrapper<BaseLiveTournament> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BaseLiveTournament::getTournamentId, tournamentId);
        queryWrapper.eq(BaseLiveTournament::getType, 0);
        queryWrapper.last("limit 1");
        BaseLiveTournament liveTournament = baseMapper.selectOne(queryWrapper);
        return liveTournament;
    }


    boolean findByStreamName(String streamName) {
        BaseLiveTournament liveTournament = getBaseLiveTournament(streamName);
        if (ObjectUtil.isNull(liveTournament)) {
            //当前房间号未使用 可以使用
            return false;
        } else {
            //当前房间号已存在
            return true;
        }

    }

    /**
     * 根据房间号获取数据
     * @param streamName
     * @return
     */
    public BaseLiveTournament getBaseLiveTournament(String streamName) {
        LambdaQueryWrapper<BaseLiveTournament> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BaseLiveTournament::getRoomNumber, streamName);
        queryWrapper.last("limit 1");
        BaseLiveTournament liveTournament = baseMapper.selectOne(queryWrapper);
        return liveTournament;
    }
}
